package com.wl.service.impl;

import cn.hutool.core.bean.BeanUtil;
import com.aliyuncs.utils.StringUtils;
import com.wl.constant.Constant;
import com.wl.controller.WebSocket;
import com.wl.mapper.ArticlesMapper;
import com.wl.mapper.CommentsMapper;
import com.wl.pojo.Articles;
import com.wl.pojo.model.ArticleManagement;
import com.wl.pojo.model.ArticleModel;
import com.wl.pojo.model.UserToken;
import com.wl.service.ArticlesService;
import com.wl.util.*;
import lombok.SneakyThrows;
import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.document.Document;
import org.apache.lucene.document.Field;
import org.apache.lucene.document.StringField;
import org.apache.lucene.document.TextField;
import org.apache.lucene.index.*;
import org.apache.lucene.queryparser.classic.QueryParser;
import org.apache.lucene.search.IndexSearcher;
import org.apache.lucene.search.Query;
import org.apache.lucene.search.ScoreDoc;
import org.apache.lucene.search.TopDocs;
import org.apache.lucene.search.highlight.Formatter;
import org.apache.lucene.search.highlight.*;
import org.apache.lucene.store.Directory;
import org.apache.lucene.store.FSDirectory;
import org.apache.lucene.util.Version;
import org.wltea.analyzer.lucene.IKAnalyzer;
import redis.clients.jedis.Jedis;

import javax.servlet.http.HttpServletRequest;
import java.io.File;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @program: treeHole
 * @author: 吴磊
 * @create: 2021-07-06 18:15
 */
public class ArticlesServiceImpl implements ArticlesService {
    private Myproperties mp = Myproperties.getMyProperties();
    private ArticlesMapper articlesMapper = MybatisUtils.getMapper(ArticlesMapper.class);
    private CommentsMapper commentsMapper = MybatisUtils.getMapper(CommentsMapper.class);


    @Override
    public Map<String, Object> getUserMayBeLike(HttpServletRequest request) {
        HashMap<String, Object> resMap = new HashMap<>();
        Jedis jedis = RedisUtil.getJedis();
        String userId = request.getParameter("userId");
        String USERID_BROWSE = userId + "_browse";
        int total = Math.toIntExact(jedis.zcard(USERID_BROWSE));
        Set<String> articleIds = new HashSet<>();
        if (total >= 20) {
            int endIndex = (int) (total * 0.6);
            Set<String> frontLabels = jedis.zrevrange(USERID_BROWSE, 0, (endIndex - 1));
            ArrayList<String> frontLabelList = new ArrayList<>(frontLabels);
            String[] array = new String[frontLabelList.size()];
            int size = frontLabelList.size();
            for (int i = 0; i < size; i++) {
                array[i] = frontLabelList.get(i);
            }
            jedis.sadd(USERID_BROWSE + "_f", array);
            Set<String> backLabels = jedis.zrevrange(USERID_BROWSE, endIndex, -1);
            ArrayList<String> backLabelList = new ArrayList<>(backLabels);
            String[] array1 = new String[backLabelList.size()];
            int size1 = backLabelList.size();
            for (int i = 0; i < size1; i++) {
                array1[i] = backLabelList.get(i);
            }
            jedis.sadd(USERID_BROWSE + "_h", array1);

            Random random = new Random();
            String id = null;
            String label = null;
            boolean flag = true;
            while (true) {
                if (flag && (random.nextInt(10) + 1) >>> 3 == 0) { //控制70%的概率取到
                    label = jedis.spop(USERID_BROWSE + "_f");
                } else {
                    label = jedis.spop(USERID_BROWSE + "_h");
                }
                if (label == null) {
                    flag = false;
                    continue;
                }
                List<String> ids = jedis.srandmember(label, 5);
                if (ids.size() == 1) {
                    id = ids.get(0);
                    if (!articleIds.contains(id)) {
                        articleIds.add(id);
                    }
                } else {
                    for (int j = 0; j < ids.size(); j++) {
                        if (!articleIds.contains(ids.get(j))) {
                            articleIds.add(ids.get(j));
                            if (articleIds.size() >= 20) {
                                break;
                            }
                        }
                    }
                }
                if (articleIds.size() >= 20) {
                    break;
                }
            }
            jedis.del(USERID_BROWSE + "_f");
            jedis.del(USERID_BROWSE + "_h");
        } else {
            Set<String> allLabels = jedis.zrevrange(USERID_BROWSE, 0, -1);
            if (allLabels.size() > 0) {
                ArrayList<String> backLabelList = new ArrayList<>(allLabels);
                String[] array1 = new String[backLabelList.size()];
                int size1 = backLabelList.size();
                for (int i = 0; i < size1; i++) {
                    array1[i] = backLabelList.get(i);
                }
                jedis.sadd(USERID_BROWSE + "_h", array1);
            }
            String id = null;
            String label = null;
            while (true) {
                label = jedis.spop(USERID_BROWSE + "_h");
                if (label == null) {
                    break;
                }
                List<String> ids = jedis.srandmember(label, 5);
                if (ids.size() == 1) {
                    id = ids.get(0);
                    if (!articleIds.contains(id)) {
                        articleIds.add(id);
                    }
                } else {
                    for (int j = 0; j < ids.size(); j++) {
                        if (!articleIds.contains(ids.get(j))) {
                            articleIds.add(ids.get(j));
                            if (articleIds.size() >= 20) {
                                break;
                            }
                        }
                    }
                }
                if (articleIds.size() >= 20) {
                    break;
                }
            }
            if (articleIds.size() < 20) {
                Integer zcard = Math.toIntExact(jedis.zcard(Constant.INTEGRAL));
                if (zcard <= 0) {
                    resMap.put("articles", new ArrayList<>());
                    return resMap;
                }
                Random random = new Random();
                while (true) {
                    int i = random.nextInt(zcard);
                    Set<String> set = jedis.zrevrange(Constant.INTEGRAL, i, i);
                    if (set == null || set.size() <= 0) {
                        continue;
                    }
                    Iterator<String> iterator = set.iterator();
                    if (iterator.hasNext()) {
                        id = iterator.next();
                    }
                    if (!articleIds.contains(id)) {
                        articleIds.add(id);
                        if (articleIds.size() >= 20) {
                            break;
                        }
                    }
                }
            }
            jedis.del(USERID_BROWSE + "_h");
        }

        List<Articles> articlesList = articlesMapper.getArticleByIdList(new ArrayList<>(articleIds));
        List<ArticleModel> articleModels = getArticleModelByArticle(articlesList, jedis, request);
        resMap.put("articles", articleModels);
        jedis.close();
        return resMap;
    }

    @Override
    public void browseArticleRecord(HttpServletRequest request) {
        Jedis jedis = RedisUtil.getJedis();
        String userId = request.getParameter("userId");
        String articleLabel = request.getParameter("articleLabel");
        String USERID_BROWSE = userId + "_browse";
        try {
            //userId+"_browse" zset
            if (articleLabel != null) {
                String[] labels = articleLabel.trim().split(" ");
                for (String label : labels) {
                    String trim = label.trim();
                    if (!StringUtils.isEmpty(trim)) {
                        if ((jedis.zrank(USERID_BROWSE, label) + "").equals("null")) {
                            jedis.zadd(USERID_BROWSE, 1, label);
                        } else {
                            jedis.zincrby(USERID_BROWSE, 1, label);
                        }
                    }
                }
            }
        } catch (Exception e) {
        } finally {
            jedis.close();
        }
    }


    @Override
    public Map<String, Object> getAllArticle(HttpServletRequest request) {
        Map<String, Object> resmap = new HashMap<>();
        String page = request.getParameter("curPage");
        int curPage = 1;
        if (page != null && Integer.parseInt(page) > 0) {
            curPage = Integer.parseInt(page);
        }
        int start = (curPage - 1) * 10;
        int total = articlesMapper.getAllArticleCount();
        List<ArticleManagement> articleManagementList = articlesMapper.getAllArticle(start);
        Jedis jedis = RedisUtil.getJedis();
        articleManagementList = getArticleManagement(articleManagementList, jedis);
        resmap.put("article", articleManagementList);
        resmap.put("total", total);
        jedis.close();
        return resmap;
    }


    @Override
    public Map<String, Object> getOwnerArticleByType(String userId, String type, String curPage) {
        HashMap<String, Object> map = new HashMap<>();
        HashMap<String, Object> resMap = new HashMap<>();
        map.put("userId", userId);
        map.put("type", type);

        Integer total = articlesMapper.getOwnerArticleByTypeCount(map);
        resMap.put("total", total);
        if (total == 0) {
            resMap.put("articles", new ArrayList<>());
            return resMap;
        }
        map.put("curPage", (new Integer(curPage) - 1) * 20);
        List<Articles> articles = articlesMapper.getOwnerArticleByType(map);
        Jedis jedis = RedisUtil.getJedis();

        List<ArticleModel> collect = articles.stream().map(article -> {
            ArticleModel articleModel = new ArticleModel();
            BeanUtil.copyProperties(article, articleModel);
            String articleContent = articleModel.getArticleContent();
            articleContent = articleContent.replaceAll("\\n", "<br/>");
            articleContent = articleContent.replaceAll("  ", "&emsp;");
            articleModel.setArticleContent(articleContent);
            String articleId = articleModel.getArticleId();
            Long upCount = jedis.scard(articleId + "_up");
            Long downCount = jedis.scard(articleId + "_down");
            String articleCommentCount = jedis.get(articleId + "_commentCount");
            articleModel.setArticleUpCount(Math.toIntExact(upCount));
            articleModel.setArticleDownCount(Math.toIntExact(downCount));
            articleModel.setArticleCommentCount(Integer.valueOf(articleCommentCount == null ? "0" : articleCommentCount));
            return articleModel;
        }).collect(Collectors.toList());
        jedis.close();
        resMap.put("articles", collect);
        return resMap;
    }

    @SneakyThrows
    @Override
    public Map<String, Object> getArticleByLabel(HttpServletRequest request) {
        Map<String, Object> resmap = new HashMap<>();
        Map<String, Object> map = new HashMap<>();
        String label = request.getParameter("label");
        String page = request.getParameter("curPage");
        int curPage = 1;
        if (page != null && Integer.parseInt(page) > 0) {
            curPage = Integer.parseInt(page);
        }
        Jedis jedis = RedisUtil.getJedis();
        Set<String> set = jedis.smembers(label);
        if (set == null || set.size() <= 0) {
            resmap.put("total", 0);
            resmap.put("article", null);
            return resmap;
        }
        map.put("set", set);
        int start = (curPage - 1) * 20;
        map.put("start", start);
        List<Articles> articleList = articlesMapper.getArticleByLabel(map);
        List<ArticleModel> articleModelList = getArticleModelByArticle(articleList, jedis, request);
        int total = set.size();
        resmap.put("total", total);
        resmap.put("article", articleModelList);
        jedis.close();
        return resmap;
    }

    @SneakyThrows
    @Override
    public void passAndRefusedArticle(HttpServletRequest request) {
        String articleId = request.getParameter("articleId");
        String type = request.getParameter("type");
        Jedis jedis = RedisUtil.getJedis();
        if (jedis.sismember(Constant.NEW_ARTICLE, articleId)) {
            jedis.srem(Constant.NEW_ARTICLE, articleId);
        }
        if ("pass".equals(type)) {
            //通过文章
            Articles articles = new Articles();
            articles.setArticleStatus("1");
            articles.setArticleId(articleId);
            articlesMapper.updateArticleById(articles);
            //更新完文章的状态，查出文章
            Articles articleById = articlesMapper.getArticleById(articleId);
            String articleLabels = articleById.getArticleLabel();
            if (!StringUtils.isEmpty(articleLabels.trim())) {
                //如果标签不为空，就把这些标签存Redis
                String[] labels = articleLabels.split(" ");
                for (String label : labels) {
                    jedis.sadd(label, articleId);
                    jedis.sadd(Constant.ALL_LABELS, label);
                }
            }
            jedis.zadd(Constant.INTEGRAL, 0, articleId);
            createIndex(articleById);
            UserToken user = TokenUtils.getUser(request);
            String userId = user.getUserId();
            WebSocket.sendMessage(articleId, userId);
        } else {
            Articles articles = new Articles();
            articles.setArticleId(articleId);
            //拒绝文章
            articlesMapper.delete(articles);
        }
        jedis.close();
    }

    @Override
    public Articles auditArticle(HttpServletRequest request) {
        int i = 0;
        Jedis jedis = RedisUtil.getJedis();
        Articles articleById;
        while (true) {
            if (i == 10) {
                return null;
            }
            String articleId = jedis.srandmember(Constant.NEW_ARTICLE);
            if (StringUtils.isEmpty(articleId)) {
                return null;
            }
            UserToken user = TokenUtils.getUser(request);
            String userId = user.getUserId();
            articleById = articlesMapper.getArticleById(articleId);
            if (userId.equals(articleById.getUserId())) {
                i++;
                continue;
            }
            String articleContent = articleById.getArticleContent();
            articleContent = articleContent.replaceAll("\\n", "<br/>");
            articleContent = articleContent.replaceAll("  ", "&emsp;");
            articleById.setArticleContent(articleContent);
            break;
        }
        jedis.close();
        return articleById;
    }

    @SneakyThrows
    @Override
    public boolean insertArticle(HttpServletRequest request, Articles articles) {
        String token = TokenUtils.parseTokenToken(request);
        UserToken loginUser = TokenUtils.parseTokenToUserToken(token);
        articles.setUserId(loginUser.getUserId());
        String articleId = MyUtil.getUUID();
        String currentDetailedTime = MyUtil.getCurrentDetailedTime();
        articles.setArticleId(articleId);
        articles.setArticleDate(currentDetailedTime);
        Integer i = articlesMapper.insert(articles);
        if (i <= 0) {
            return false;
        }
        Jedis jedis = RedisUtil.getJedis();
        jedis.sadd(Constant.NEW_ARTICLE, articleId);
        jedis.close();
        return true;
    }

    @SneakyThrows
    @Override
    public boolean deleteArticleById(Articles articles) {
        Articles article = articlesMapper.getArticleById(articles.getArticleId());
        String articleId = article.getArticleId();
        String articleLabels = article.getArticleLabel();
        Integer i = articlesMapper.delete(articles);
        if (i <= 0) {
            return false;
        }
        Jedis jedis = RedisUtil.getJedis();

        if (jedis.sismember(Constant.NEW_ARTICLE, articleId)) {
            jedis.srem(Constant.NEW_ARTICLE, articleId);
        } else {
            //删除所有标签
            if (!StringUtils.isEmpty(articleLabels.trim())) {
                String[] labels = articleLabels.split(" ");
                for (String label : labels) {
                    jedis.sadd(label, articleId);
                }
            }
            //删除所有点赞和踩赞和点赞数量
            jedis.del(articleId + "_up");
            jedis.del(articleId + "_down");
            jedis.del(articleId + "_commentCount");
            //删除对应的积分
            jedis.zrem(Constant.INTEGRAL, articleId);
            //删除数据库里面的所有评论
            commentsMapper.deleteCommentByArticleId(articleId);
            deleteIndex(articleId);
        }
        jedis.close();
        return true;
    }

    @SneakyThrows
    @Override
    public ArticleModel getOneArticleById(HttpServletRequest request, String articleId) {
        Articles article = articlesMapper.getArticleById(articleId);
        ArticleModel articleModel = new ArticleModel();
        BeanUtil.copyProperties(article, articleModel);
        String articleLabels = article.getArticleLabel();
        if (!StringUtils.isEmpty(articleLabels)) {
            String[] labels = articleLabels.split(" ");
            ArrayList<String> labelList = new ArrayList<>();
            for (String label : labels) {
                labelList.add(label);
            }
            articleModel.setArticleLabels(labelList);
        }
        Jedis jedis = RedisUtil.getJedis();
        Long upCount = jedis.scard(articleId + "_up");
        Long downCount = jedis.scard(articleId + "_down");
        String commentCount = jedis.get(articleId + "_commentCount");
        if (commentCount == null) {
            articleModel.setArticleCommentCount(0);
        } else {
            articleModel.setArticleCommentCount(Integer.parseInt(commentCount));
        }
        articleModel.setArticleUpCount(Integer.parseInt(upCount + ""));
        articleModel.setArticleDownCount(Integer.parseInt(downCount + ""));
        String token = TokenUtils.parseTokenToken(request);
        UserToken userToken = TokenUtils.parseTokenToUserToken(token);
        if (userToken != null) {
            articleModel.setArticleIsUp(jedis.sismember(articleId + "_up", userToken.getUserId()));
            articleModel.setArticleIsDown(jedis.sismember(articleId + "_down", userToken.getUserId()));
            articleModel.setBeLongToOwner(article.getUserId().equals(userToken.getUserId()));
        }
        jedis.close();
        return articleModel;
    }

    @SneakyThrows
    @Override
    public Long articleUp(HttpServletRequest request, String articleId) {
        Jedis jedis = RedisUtil.getJedis();
        if ((jedis.zrank(Constant.INTEGRAL, articleId) + "").equals("null")) {
            jedis.close();
            return -2L;
        }
        String token = TokenUtils.parseTokenToken(request);
        UserToken userToken = TokenUtils.parseTokenToUserToken(token);
        String userId = userToken.getUserId();

        String articleIdDownSet = articleId + "_down";
        if (jedis.sismember(articleIdDownSet, userId)) {
            return -1L;
        }
        String articleIdSet = articleId + "_up";
        if (jedis.sismember(articleIdSet, userId)) {
            jedis.srem(articleIdSet, userId);
            RedisUtil.setIntegralByStep(Constant.INTEGRAL, articleId, jedis);
        } else {
            jedis.sadd(articleIdSet, userId);
            RedisUtil.setIntegralByPraise(Constant.INTEGRAL, articleId, jedis);
        }
        Long articleIdSetCount = jedis.scard(articleIdSet);
        jedis.close();
        return articleIdSetCount;
    }

    @SneakyThrows
    @Override
    public Long articleDown(HttpServletRequest request, String articleId) {
        Jedis jedis = RedisUtil.getJedis();
        if ((jedis.zrank(Constant.INTEGRAL, articleId) + "").equals("null")) {
            jedis.close();
            return -2L;
        }
        String token = TokenUtils.parseTokenToken(request);
        UserToken userToken = TokenUtils.parseTokenToUserToken(token);
        String userId = userToken.getUserId();
        String articleIdSUpSet = articleId + "_up";
        if (jedis.sismember(articleIdSUpSet, userId)) {
            return -1L;
        }
        String articleIdSet = articleId + "_down";
        if (jedis.sismember(articleIdSet, userId)) {
            jedis.srem(articleIdSet, userId);
            RedisUtil.setIntegralByPraise(Constant.INTEGRAL, articleId, jedis);
        } else {
            jedis.sadd(articleIdSet, userId);
            RedisUtil.setIntegralByStep(Constant.INTEGRAL, articleId, jedis);
        }
        Long articleIdSetCount = jedis.scard(articleIdSet);
        jedis.close();
        return articleIdSetCount;
    }


    @SneakyThrows
    @Override
    public Map<String, Object> getArticleBySome(HttpServletRequest request) {
        if (request.getParameter("type").equals("label")) {
            Map<String, Object> map = getArticleByLabel(request);
            return map;
        }
        Jedis jedis = RedisUtil.getJedis();
        Map<String, Object> resMap = new HashMap<>();
        Integer articlesCount = 0;
        List<Articles> allArticlesList = null;
        List<Articles> articlesList = null;
        List<ArticleModel> articleModelList = null;
        Map<String, Object> map = null;
        Set<String> idSet = null;
        String page = request.getParameter("curPage");
        int curPage = 1;
        if (page != null && Integer.parseInt(page) > 0) {
            curPage = Integer.parseInt(page);
        }
        String userId = request.getParameter("userId");
        if (userId != null) {
            int status = Integer.valueOf(request.getParameter("status") == null ? 1 : Integer.valueOf(request.getParameter("status")));
            //查询自己的
            map = new HashMap<>();
            map.put("userId", userId);
            map.put("status", status);
            articlesCount = articlesMapper.getArticleByUseridAndStatusCount(map);
            int start = (curPage - 1) * 20;
            map.put("start", start);
            articlesList = articlesMapper.getArticleByPage(map);
            articleModelList = getArticleModelByArticle(articlesList, jedis, request);
        } else {
            if ("hot".equals(request.getParameter("type"))) {
                int start = (curPage - 1) * 20;
                idSet = jedis.zrevrange(Constant.INTEGRAL, start, start + 19);
                articlesCount = Math.toIntExact(jedis.zcard(Constant.INTEGRAL));
                List<String> idList = new ArrayList<>(idSet);
                map = new HashMap<>();
                map.put("ids", idList);
                articlesList = articlesMapper.getArticleBySome(map);
                articlesList = articleSorted(idList, articlesList);
                articleModelList = getArticleModelByArticle(articlesList, jedis, request);
            } else if ("essence-24".equals(request.getParameter("type"))) {
                Long Count = jedis.zcard(Constant.INTEGRAL);
                idSet = jedis.zrevrange(Constant.INTEGRAL, 0, Count);
                List<String> idList = new ArrayList<>(idSet);
                map = new HashMap<>();
                Long nowTime = System.currentTimeMillis();
                String time = MyUtil.parseLongTimeToString(nowTime - 86400000);
                map.put("time", time);
                allArticlesList = articlesMapper.getArticleByListId(map);
                articlesCount = allArticlesList.size();
                articlesList = articleSorted(idList, allArticlesList);
                int start = (curPage - 1) * 20;
                int end = start + 20;
                if (end > articlesList.size()) {
                    end = articlesList.size();
                }
                articlesList = articlesList.subList(start, end);
                articleModelList = getArticleModelByArticle(articlesList, jedis, request);
            } else if ("essence-7".equals(request.getParameter("type"))) {
                Long Count = jedis.zcard(Constant.INTEGRAL);
                idSet = jedis.zrevrange(Constant.INTEGRAL, 0, Count);
                List<String> idList = new ArrayList<>(idSet);
                map = new HashMap<>();
                Long nowTime = System.currentTimeMillis();
                String time = MyUtil.parseLongTimeToString(nowTime - 604800000);
                map.put("time", time);
                allArticlesList = articlesMapper.getArticleByListId(map);
                articlesCount = allArticlesList.size();
                articlesList = articleSorted(idList, allArticlesList);
                int start = (curPage - 1) * 20;
                int end = start + 20;
                if (end > articlesList.size()) {
                    end = articlesList.size();
                }
                articlesList = articlesList.subList(start, end);
                articleModelList = getArticleModelByArticle(articlesList, jedis, request);
            } else if ("essence-30".equals(request.getParameter("type"))) {
                Long Count = jedis.zcard(Constant.INTEGRAL);
                idSet = jedis.zrevrange(Constant.INTEGRAL, 0, Count);
                List<String> idList = new ArrayList<>(idSet);
                map = new HashMap<>();
                Long nowTime = System.currentTimeMillis();
                String time = MyUtil.parseLongTimeToString(nowTime - (604800000 * 30));
                map.put("time", time);
                allArticlesList = articlesMapper.getArticleByListId(map);
                articlesCount = allArticlesList.size();
                articlesList = articleSorted(idList, allArticlesList);
                int start = (curPage - 1) * 20;
                int end = start + 20;
                if (end > articlesList.size()) {
                    end = articlesList.size();
                }
                articlesList = articlesList.subList(start, end);
                articleModelList = getArticleModelByArticle(articlesList, jedis, request);
            } else if ("new".equals(request.getParameter("type"))) {
//                SqlSession sqlSession = MybatisUtils.getSqlSession();
//                sqlSession.clearCache();
//                ArticlesMapper articlesMapper = sqlSession.getMapper(ArticlesMapper.class);
//                articlesCount = articlesMapper.getArticleByTime();
                articlesCount = Math.toIntExact(jedis.zcard(Constant.INTEGRAL));
                int start = (curPage - 1) * 20;
                articlesList = articlesMapper.getArticleByTimeAndPage(start);
                articleModelList = getArticleModelByArticle(articlesList, jedis, request);
            }
        }
        jedis.close();
        int total = articlesCount;
        if (total == 0) {
            resMap.put("total", 0);
            resMap.put("article", new ArrayList<>());
            return resMap;
        }
        resMap.put("total", total);
        resMap.put("article", articleModelList);
        return resMap;
    }

    @SneakyThrows
    private List<Articles> articleSorted(List<String> list, List<Articles> articlesList) {
        List<Articles> articlesSortList = new ArrayList<>();
        for (Articles articles : articlesList) {
            String articleId = articles.getArticleId();
            int index = list.indexOf(articleId);
            articles.setArticleStatus(String.valueOf(index));
            articlesSortList.add(articles);
        }
        Collections.sort(articlesSortList, (article1, article2) -> {
            int status1 = Integer.parseInt(article1.getArticleStatus());
            int status2 = Integer.parseInt(article2.getArticleStatus());
            if (status1 > status2) {
                return 1;
            }
            if (status1 == status2) {
                return 0;
            }
            return -1;
        });
        return articlesSortList;
    }

    private List<ArticleManagement> getArticleManagement(List<ArticleManagement> articlesList, Jedis jedis) {
        if (articlesList == null || articlesList.size() <= 0) {
            return null;
        }
        List<ArticleManagement> articleModels = articlesList.stream().map(article -> {
            Long upCount = jedis.scard(article.getArticleId() + "_up");
            Long downCount = jedis.scard(article.getArticleId() + "_down");
            String commentCount = jedis.get(article.getArticleId() + "_commentCount");
            if (commentCount == null) {
                article.setArticleCommentCount(0);
            } else {
                article.setArticleCommentCount(Integer.parseInt(commentCount));
            }
            article.setArticleUpCount(Integer.parseInt(upCount + ""));
            article.setArticleDownCount(Integer.parseInt(downCount + ""));
            return article;
        }).collect(Collectors.toList());
        return articleModels;
    }

    private List<ArticleModel> getArticleModelByArticle(List<Articles> articlesList, Jedis jedis, HttpServletRequest request) {
        if (articlesList == null || articlesList.size() <= 0) {
            return null;
        }
        UserToken userToken = TokenUtils.getUser(request);
        List<ArticleModel> articleModels = articlesList.stream().map(article -> {
            ArticleModel articleModel = new ArticleModel();
            BeanUtil.copyProperties(article, articleModel);
            String articleContent = articleModel.getArticleContent();
            articleContent = articleContent.replaceAll("\\n", "<br/>");
            articleContent = articleContent.replaceAll("  ", "&emsp;");
            articleModel.setArticleContent(articleContent);
            String articleLabels = article.getArticleLabel();
            ArrayList<String> labelList = new ArrayList<>();
            if (!StringUtils.isEmpty(articleLabels)) {
                String[] labels = articleLabels.split(" ");
                for (String label : labels) {
                    labelList.add(label);
                }
            }
            articleModel.setArticleLabels(labelList);
            Long upCount = jedis.scard(article.getArticleId() + "_up");
            Long downCount = jedis.scard(article.getArticleId() + "_down");
            String commentCount = jedis.get(article.getArticleId() + "_commentCount");
            if (commentCount == null) {
                articleModel.setArticleCommentCount(0);
            } else {
                articleModel.setArticleCommentCount(Integer.parseInt(commentCount));
            }
            articleModel.setArticleUpCount(Integer.parseInt(upCount + ""));
            articleModel.setArticleDownCount(Integer.parseInt(downCount + ""));
            if (userToken != null) {
                articleModel.setArticleIsUp(jedis.sismember(article.getArticleId() + "_up", userToken.getUserId()));
                articleModel.setArticleIsDown(jedis.sismember(article.getArticleId() + "_down", userToken.getUserId()));
                articleModel.setBeLongToOwner(article.getUserId().equals(userToken.getUserId()));
            }
            return articleModel;
        }).collect(Collectors.toList());
        return articleModels;
    }

    /**
     * 创建索引，后面要改到审批文章处
     *
     * @param articles
     * @return
     */
    @SneakyThrows
    public void createIndex(Articles articles) {
        Document document = new Document();
        // 创建并添加字段信息。参数：字段的名称、字段的值、是否存储，这里选Store.YES代表存储到文档列表。Store.NO代表不存储
        document.add(new StringField("articleId", articles.getArticleId(), Field.Store.YES));
        document.add(new StringField("userId", articles.getUserId(), Field.Store.YES));
        document.add(new StringField("label", articles.getArticleLabel(), Field.Store.YES));
        document.add(new StringField("date", articles.getArticleDate(), Field.Store.YES));
        document.add(new StringField("status", "1", Field.Store.YES));
        // 这里我们title字段需要用TextField，即创建索引又会被分词。
        document.add(new TextField("Content", articles.getArticleContent(), Field.Store.YES));
        //2 索引目录类,指定索引在硬盘中的位置
        Directory directory;
        String osName = System.getProperty("os.name");
        if (osName.toLowerCase().startsWith("win")) {
            directory = FSDirectory.open(new File(mp.getProperty("linuxPath.win")));
        } else {
            directory = FSDirectory.open(new File(mp.getProperty("linuxPath.linux")));
        }
        //3 创建分词器对象
        //Analyzer analyzer = new StandardAnalyzer();
        Analyzer analyzer = new IKAnalyzer();
        //4 索引写出工具的配置对象
        IndexWriterConfig conf = new IndexWriterConfig(Version.LATEST, analyzer);
        //conf.setOpenMode(IndexWriterConfig.OpenMode.CREATE);//会删除之前的索引然后再创建
        //5 创建索引的写出工具类。参数：索引的目录和配置信息
        IndexWriter indexWriter = new IndexWriter(directory, conf);

        //6 把文档交给IndexWriter
        indexWriter.addDocument(document);
        //7 提交
        indexWriter.commit();
        //8 关闭
        indexWriter.close();
    }

    @SneakyThrows
    private void deleteIndex(String articleId) {
        // 创建目录对象
        Directory directory;
        String osName = System.getProperty("os.name");
        if (osName.toLowerCase().startsWith("win")) {
            directory = FSDirectory.open(new File(mp.getProperty("linuxPath.win")));
        } else {
            directory = FSDirectory.open(new File(mp.getProperty("linuxPath.linux")));
        }
        // 创建配置对象
        IndexWriterConfig conf = new IndexWriterConfig(Version.LATEST, new IKAnalyzer());
        // 创建索引写出工具
        IndexWriter writer = new IndexWriter(directory, conf);

        // 根据词条进行删除
        writer.deleteDocuments(new Term("articleId", articleId));

        // 根据query对象删除,如果ID是数值类型，那么我们可以用数值范围查询锁定一个具体的ID
        //		Query query = NumericRangeQuery.newLongRange("id", 2L, 2L, true, true);
        //		writer.deleteDocuments(query);

        // 删除所有
        //writer.deleteAll();
        // 提交
        writer.commit();
        // 关闭
        writer.close();
    }

    @Override
    @SneakyThrows
    public Map<String, Object> searchArticles(HttpServletRequest request) {
        int curPage = 1;
        if (request.getParameter("curPage") != null) {
            curPage = Integer.parseInt(request.getParameter("curPage"));
        }
        int start = (curPage - 1) * 20;
        int end = start + 20;
        Map<String, Object> map = new HashMap<>();
        List<Articles> articlesList = new ArrayList<>();
        List<ArticleModel> articleModelList;
        Articles articles = null;
        String keywords = request.getParameter("keywords");
        // 目录对象
        Directory directory;
        String osName = System.getProperty("os.name");
        if (osName.toLowerCase().startsWith("win")) {
            directory = FSDirectory.open(new File(mp.getProperty("linuxPath.win")));
        } else {
            directory = FSDirectory.open(new File(mp.getProperty("linuxPath.linux")));
        }
        // 创建读取工具
        IndexReader reader = DirectoryReader.open(directory);
        // 创建搜索工具
        IndexSearcher searcher = new IndexSearcher(reader);
        QueryParser parser = new QueryParser("Content", new IKAnalyzer());
        Query query = parser.parse(keywords);
        // 格式化器
        Formatter formatter = new SimpleHTMLFormatter("<span style='color: red;font-size: 16px'>", "</span>");
        QueryScorer scorer = new QueryScorer(query);
        //393765
        //558674
        // 准备高亮工具
        Highlighter highlighter = new Highlighter(formatter, scorer);
        highlighter.setTextFragmenter(new SimpleFragmenter(100000));
        // 搜索
        TopDocs topDocs = searcher.search(query, end);
        int totalpages = (topDocs.totalHits + 20 - 1) / 20;
        if (totalpages == 0) {
            map.put("total", 0);
            map.put("totalpages", 0);
            map.put("article", new ArrayList<>());
            return map;
        }
        map.put("total", topDocs.totalHits);
        map.put("totalpages", totalpages);
        ScoreDoc[] scoreDocs = topDocs.scoreDocs;
        if (end > scoreDocs.length) {
            end = scoreDocs.length;
        }
        for (int i = start; i < end; i++) {
            ScoreDoc scoreDoc = scoreDocs[i];
            // 获取文档编号
            int docID = scoreDoc.doc;
            Document doc = reader.document(docID);
            if (doc.get("status").equals("0")) {
                continue;
            }
            articles = new Articles();
            articles.setArticleId(doc.get("articleId"));
            articles.setUserId(doc.get("userId"));
            articles.setArticleLabel(doc.get("label"));
            articles.setArticleDate(doc.get("date"));
            articles.setArticleStatus(doc.get("status"));
            String title = doc.get("Content");
            // 用高亮工具处理普通的查询结果,参数：分词器，要高亮的字段的名称，高亮字段的原始值
            String hTitle = highlighter.getBestFragment(new IKAnalyzer(), "Content", title);
            articles.setArticleContent(hTitle);
            articlesList.add(articles);
            // 获取文档的得分
        }
        Jedis jedis = RedisUtil.getJedis();
        articleModelList = getArticleModelByArticle(articlesList, jedis, request);
        map.put("article", articleModelList);
        jedis.close();
        return map;
    }
}
